/**
 * 自定义时间选择组件，支持日期选择和月份选择
 * by zhangxinyue
 * create 2020-08-31
 */
import { QuestionCircleOutlined } from '@ant-design/icons';

import { Form } from '@ant-design/compatible';
import '@ant-design/compatible/assets/index.css';

import { DatePicker, Tooltip } from 'antd';
import { connect } from 'dva';
import moment from 'moment';
import PropTypes from 'prop-types';
import React, { Component } from 'react';

import { FormItemLayout, NoLableLayout } from '../formPub';

class SingleDateC extends Component {
  // props默认值
  // eslint-disable-next-line react/static-property-placement
  static defaultProps = {
    title: '',
    placeholder: '请选择日期',
    helper: '',
    onChange: () => {},
    dataType: 'date', // 默认是年月日类型
    disableBegin: '',
    disableEnd: '',
    disabled: false,
    onRef: () => {}, // 本组件的引用
    formItemLayout: FormItemLayout,
    allowClear: true,
    labalWrap: false, // 默认title不换行
    onOpenChange: () => {}, // 弹出日历和关闭日历的回调
    valueType: 'date', // 默认month时抛出年月类型，
    // {calendarType: 1}-交易所 {calendarType: 2}银行间
  };

  constructor(props) {
    super(props);
    this.state = {
      isOpen: false, // year 面板打开关闭
    };
  }

  componentDidMount() {
    // 父组件对本组件的引用
    this.props.onRef(this);

    // 如果年月类型，抛出的是时间区间，则需要调用下change时间，父组件才能拿到时间区间
    if (this.props.valueType == 'range' && this.props.dataType == 'month' && this.props.initialValue) {
      this.monthChange(this.props.initialValue);
    }
    if (this.props.useDisabledDate) {
      this.getDisabled();
    }
  }

  // 非初始化状态下更改时间(供父组件调用)
  // eslint-disable-next-line react/no-unused-class-component-methods
  setDate = (value) => {
    const valueF = {};
    valueF[this.props.dataIndex] = value;
    this.props.form.setFieldsValue(valueF);
    // 如果年月类型，抛出的是时间区间，则需要调用下change时间，父组件才能拿到时间区间
    if (this.props.valueType == 'range' && this.props.dataType == 'month') {
      this.monthChange(value);
    }
  };

  getDisabled = () => {
    const {
      useDisabledDate: { calendarType },
    } = this.props;
    this.props.dispatch({
      type: 'globalM/queryHoliday',
      payload: {
        startDate: moment().startOf('year').format('YYYY-MM-DD'),
        endDate: moment().format('YYYY-MM-DD'),
        calendarType,
      },
      callback: (type, data) => {
        if (type == 'success') {
          const arr = [];
          // eslint-disable-next-line no-unused-vars
          for (const arrElement of data) {
            if (arrElement.isHoliday === 0) {
              let str = arrElement.currentDate;
              const a = str.split('');
              a.splice(4, 0, '-');
              a.splice(7, 0, '-');
              str = a.join('');
              arr.push(str);
            }
          }
          this.setState({
            dateList: arr,
          });
        }
      },
    });
  };

  // 禁选日期设定
  disabledDate = (value) => {
    const { disableBegin, disableEnd, useDisabledDate } = this.props;
    /**
     * 禁用非交易日
     */
    if (useDisabledDate) {
      const { dateList = [] } = this.state;
      return (
        dateList.some((item) => {
          const date = moment(item);
          const currentDate = moment(value).format('YYYY-MM-DD');
          return date.isSame(currentDate);
        }) ||
        value < moment().startOf('year') ||
        value > (disableEnd || moment())
      );
    }
    // 全部禁用传null
    if (disableBegin === null && disableEnd === null) return true;

    const valueF = value.format('YYYYMMDD');
    const disBeginF = disableBegin === '' || disableBegin === undefined ? '' : disableBegin.format('YYYYMMDD');
    const disEndF = disableEnd === '' || disableEnd === undefined ? moment().format('YYYYMMDD') : disableEnd.format('YYYYMMDD');

    if (disableEnd === '' || disableEnd === undefined) {
      return valueF <= disBeginF;
    }
    return valueF <= disBeginF || valueF >= disEndF;
  };

  // 禁选月份
  disabledDateMonth = (value) => {
    const { disableBegin, disableEnd } = this.props;
    // 全部禁用传null
    if (disableBegin === null && disableEnd === null) return true;

    const valueF = value.format('YYYYMM');
    const disBeginF = disableBegin === '' || disableBegin === undefined ? '' : disableBegin.format('YYYYMM');
    const disEndF = disableEnd === '' || disableEnd === undefined ? moment().format('YYYYMM') : disableEnd.format('YYYYMM');

    if (disableEnd === '' || disableEnd === undefined) {
      return valueF <= disBeginF;
    }
    return valueF <= disBeginF || valueF >= disEndF;
  };

  // valueType=range时调用，向外抛出时间区间
  monthChange = (e) => {
    if (!e) {
      this.props.onChange();
      return;
    }
    if (this.props.valueType == 'date') {
      // 抛出值YYYY-MM
      this.props.onChange(moment(e).format('YYYY-MM'));
      return;
    }
    // 找到首日
    const startDate = e.format('YYYY-MM-01');

    let endDate = new Date(e);
    /**
     * getMonth()获取当前月份，返回值是0-11，
     */
    let month = endDate.getMonth();
    /**
     * getFullYear()获取当前年份，++month就是下个月，1代表1号，nextMonthFirstDay就是下个月1号了
     */

    // eslint-disable-next-line no-plusplus
    const nextMonthFirstDay = new Date(endDate.getFullYear(), ++month, 1);
    /**
     * 下个月1号减去1天（1000毫秒*1分钟60秒*1小时60分钟*1天24小时）
     * 生成这个月最后一天
     */
    endDate = new Date(nextMonthFirstDay - 1000 * 60 * 60 * 24);
    /**
     * 将生成的当月最后一天转化为指定格式(YYYY-MM-DD)
     */
    endDate = `${endDate.getFullYear()}-${endDate.getMonth() + 1 < 10 ? `0${endDate.getMonth() + 1}` : endDate.getMonth() + 1}-${endDate.getDate()}`;
    this.props.onChange({ startDate, endDate });
  };

  // 禁选年份 不能选未来
  disabledDateYear = (current) => {
    const year = current.format('YYYY');
    return year > moment().endOf('year').format('YYYY');
  };

  // 年份开关
  handleOpenChange = (status) => {
    this.setState({
      isOpen: status,
    });
  };

  // 面板改变的时候调用
  onPanelChange = (e) => {
    const { dataIndex } = this.props;
    this.setState(
      {
        isOpen: false,
      },
      () => {
        this.props.form.setFieldsValue({
          [dataIndex]: moment(e, 'YYYY'),
        });
        this.props.onChange(moment(e).format('YYYY'));
      },
    );
  };

  render() {
    const { styleRow, helper, title, dataType, form, dataIndex, initialValue, placeholder, disabled, formItemLayout, onChange, allowClear, onOpenChange } = this.props;
    const { getFieldDecorator } = form;
    const { MonthPicker } = DatePicker;

    return (
      <Form.Item
        // className={labalWrap ? "labalWrap" : ''}
        labelCol={title ? formItemLayout.labelCol : NoLableLayout.labelCol}
        wrapperCol={title ? formItemLayout.wrapperCol : NoLableLayout.wrapperCol}
        label={
          // eslint-disable-next-line no-nested-ternary
          title ? (
            helper ? (
              <span>
                {title}
                &nbsp;
                <Tooltip title={helper}>
                  <QuestionCircleOutlined />
                </Tooltip>
              </span>
            ) : (
              <span>{title}</span>
            )
          ) : undefined
        }
      >
        {getFieldDecorator(dataIndex, {
          initialValue,
          rules: this.props.rules,
        })(
          // eslint-disable-next-line no-nested-ternary
          dataType === 'date' ? (
            <DatePicker
              onChange={onChange}
              onOpenChange={onOpenChange}
              placeholder={placeholder}
              disabled={disabled}
              allowClear={allowClear}
              disabledDate={this.disabledDate}
              style={styleRow || { width: '100%' }}
            />
          ) : dataType === 'year' ? (
            <DatePicker
              placeholder={placeholder}
              disabled={disabled}
              allowClear={allowClear}
              open={this.state.isOpen}
              format='YYYY'
              onPanelChange={this.onPanelChange}
              onOpenChange={this.handleOpenChange}
              onChange={onChange}
              disabledDate={this.disabledDateYear}
              mode={dataType}
              style={styleRow || { width: '100%' }}
            />
          ) : (
            <MonthPicker
              onChange={this.monthChange}
              allowClear={allowClear}
              placeholder={placeholder}
              disabled={disabled}
              disabledDate={this.disabledDateMonth}
              style={styleRow || { width: '100%' }}
            />
          ),
        )}
      </Form.Item>
    );
  }
}

// props类型
SingleDateC.propsTypes = {
  labalWrap: PropTypes.bool, // 支持标题换行
  form: PropTypes.object, // form对象
  title: PropTypes.string, // 显示名称
  dataIndex: PropTypes.string, // Form识别的Item ID
  initialValue: PropTypes.string, // 初始默认值
  placeholder: PropTypes.string, // 占位符
  onChange: PropTypes.func, // 输入框内容变化时的回调
  helper: PropTypes.oneOfType([
    // 提示帮助信息
    PropTypes.string,
    PropTypes.element,
  ]),
  dataType: PropTypes.string, // 日期控件类型（年月日类型：date，年月类型：month,年：year）
  disableBegin: PropTypes.object, // 禁选起始日期（全部禁用传null，不需要禁用，则不传）
  disableEnd: PropTypes.object, // 禁选结束日期（全部禁用传null，不需要禁用，则不传）
  onRef: PropTypes.func, // 本组件的引用（可用来父组件调用内部方法）
  disabled: PropTypes.bool,
  formItemLayout: PropTypes.object, // 布局
  allowClear: PropTypes.bool, // 删除按钮控制
  rules: PropTypes.array, // 校验规则
  onOpenChange: PropTypes.func, // 弹出日历和关闭日历的回调
  valueType: PropTypes.string, // valueType只在dateType:month时生效 表示value值抛出的是YYYY-MM 还是时间区间2023-02-01至2023-02-28（ 年月：date，具体时间区间：range）
  useDisabledDate: PropTypes.shape({
    calendarType: PropTypes.number,
  }), // 是否使用非交易日disabled组件 {calendarType: 1}-交易所 {calendarType: 2}银行间
};

export default connect()(SingleDateC);
